#include "stdafx.h"
#include "..\..\cz_def.h"
#include "..\..\function\cz_log.h"
#include "file_def.h"
#include "FileWritterPool.h"

FileWritterPool::FileWritterPool()
{
	Clear();
}

FileWritterPool::~FileWritterPool()
{
	Uninit();
}

bool FileWritterPool::Init(IN stringc& strFile, IN u32 useMemory)
{
	Uninit();

	m_useMemory = useMemory;

	m_hFile = CreateFileA(strFile.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
	if (m_hFile == INVALID_HANDLE_VALUE)
	{
		CZ_LOG_ERRORA("");
		goto L_Failed;
	}

	m_pool = (u8*)malloc(m_useMemory);
	if (m_pool == NULL)
	{
		CZ_LOG_ERRORA("");
		goto L_Failed;
	}

	return true;

L_Failed:
	Uninit();
	return false;
}

void FileWritterPool::Uninit()
{
	if ((m_hFile != INVALID_HANDLE_VALUE) && (m_pool != NULL) && (m_fillSize != 0))
	{
		ForceToWrite();
	}
	if (m_hFile != INVALID_HANDLE_VALUE) CloseHandle(m_hFile);
	if (m_pool != NULL) free(m_pool);

	Clear();
}

bool FileWritterPool::WriteData(IN u8c* data, IN u32 size)
{
	if (u32AddOverflow(m_fillSize, size))
	{
		if (!WriteDataToFileDirect(data, size))
		{
			CZ_LOG_ERRORA("");
			return false;
		}
		return true;
	}
	else if ((m_fillSize + size) > m_useMemory)
	{
		if (!ForceToWrite())
		{
			CZ_LOG_ERRORA("");
			return false;
		}

		if (size > m_useMemory)
		{
			if (!WriteDataToFileDirect(data, size))
			{
				CZ_LOG_ERRORA("");
				return false;
			}
			return true;
		}
	}

	memcpy(m_pool + m_fillSize, data, size);
	m_fillSize += size;
	
	return true;
}

bool FileWritterPool::Writeu64(IN u64 v)
{
	return WriteData((u8*)&v, 8);
}

bool FileWritterPool::Writeu32(IN u32 v)
{
	return WriteData((u8*)&v, 4);
}

bool FileWritterPool::Writeu16(IN u16 v)
{
	return WriteData((u8*)&v, 2);
}

bool FileWritterPool::Writeu8(IN u8 v)
{
	return WriteData((u8*)&v, 1);
}

bool FileWritterPool::ForceToWrite()
{
	if (!WriteDataToFileDirect(m_pool, m_fillSize))
	{
		CZ_LOG_ERRORA("");
		return false;
	}
	m_fillSize = 0;
	return true;
}

void FileWritterPool::Clear()
{
	m_useMemory = 0;

	m_hFile = INVALID_HANDLE_VALUE;

	m_pool = 0;
	m_fillSize = 0;
}

bool FileWritterPool::WriteDataToFileDirect(IN u8c* data, IN u32 size)
{
	DWORD dwBytesWritten;
	u32 t;

	if (size == 0) return true;

	t = 0;
	while(true)
	{
		if (WriteFile(m_hFile, data + t, size - t, &dwBytesWritten, NULL) == FALSE)
		{
			CZ_LOG_ERRORA("");
			return false;
		}
		t += dwBytesWritten;
		if (t == size) break;
		if (t > size)
		{
			CZ_LOG_ERRORA("");
			return false;
		}
	}

	return true;
}